﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace WzhAddon
{
	public class AutoTrackObjectMgr : MonoBehaviour
	{
		private static AutoTrackObjectMgr _instance;
		public static bool defaultUpdateBeforeNextFrame = true;
		private List<AutoTrackObject.AutoTrackObjectController> waitForLateUpdate = new List<AutoTrackObject.AutoTrackObjectController>();
		private List<Action> preLateUpdate = new List<Action>();
		private List<Component> lockingComponents = new List<Component>();
		private List<Component> releasedComponents = new List<Component>();
		public static AutoTrackObjectMgr Instance { get { return _instance; } }
		public static AutoTrackObjectMgr Install(GameObject container)
		{
			if (_instance == null)
			{
				_instance = container.AddComponent<AutoTrackObjectMgr>();
				_instance.Init();
			}
			return _instance;
		}
		public void Init()
		{
			base.StartCoroutine(this.ResetStateCo());
		}

		private void OnLevelWasLoaded(int level)
		{
			base.StopAllCoroutines();
			base.StartCoroutine(this.ResetStateCo());
		}
		public void RegisterLateUpdateLock(Component c)
		{
			this.lockingComponents.Add(c);
		}
		public void ReleaseLateUpdateLock(Component c)
		{
			this.releasedComponents.Add(c);
			if (this.releasedComponents.Count<Component>() >= this.lockingComponents.Count<Component>())
			{
				this.PerformWaitedLateUpdate();
			}
		}
		public void RegisterPreLateUpdate(Action action)
		{
			this.preLateUpdate.Add(action);
		}
		public void DoLateUpdate(AutoTrackObject.AutoTrackObjectController atc)
		{
			if (this.releasedComponents.Count<Component>() >= this.lockingComponents.Count<Component>())
			{
				this.PerformAndReleasePreLateUpdate();
				atc.DoLateUpdate();
				return;
			}
			this.waitForLateUpdate.Add(atc);
		}
		public void PerformWaitedLateUpdate()
		{
			this.PerformAndReleasePreLateUpdate();
			foreach (AutoTrackObject.AutoTrackObjectController autoTrackObjectController in this.waitForLateUpdate)
			{
				autoTrackObjectController.DoLateUpdate();
			}
		}
		public void PerformAndReleasePreLateUpdate()
		{
			foreach (Action action in this.preLateUpdate)
			{
				try
				{
					action();
				}
				catch (Exception)
				{
				}
			}
			this.preLateUpdate = new List<Action>();
		}

		private IEnumerator ResetStateCo()
		{
			for (;;)
			{
				yield return new WaitForEndOfFrame();
				this.preLateUpdate = new List<Action>();
				this.waitForLateUpdate = new List<AutoTrackObject.AutoTrackObjectController>();
				this.lockingComponents = new List<Component>();
				this.releasedComponents = new List<Component>();
			}
			//yield break;
		}

	
	}
}
